package com.mycat.task.core.impl;

import com.mycat.task.core.ITaskService;
import com.mycat.task.dao.mapper.ScheduleTaskMapper;
import com.mycat.task.entity.ScheduleTask;
import com.mycat.task.proxy.ScheduleJobProxy;
import org.quartz.*;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Component;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * ${DESCRIPTION}
 *
 * @author roger.
 * @email 190642964@qq.com
 * @create 2017-03-27
 */
@Component
public class TaskService implements ITaskService,ApplicationContextAware {

    static Integer num = 1;

    public TaskService(){
        System.out.println("初始化..................................定时任务核心");
    }

    @Autowired
    private ScheduleTaskMapper scheduleTaskMapper;

    private ApplicationContext applicationContext;

    @Autowired
    private SchedulerFactoryBean schedulerFactoryBean;

    /**
     * 存放所有的任务<任务ID，ScheduleTask>
     */
    Map<String,ScheduleTask> allTask = new LinkedHashMap<>();


    @Override
    public Map<String, String> getAllCron() {
        return null;
    }

    @Override
    public List<ScheduleTask> getAllTask() {

        if(allTask.size() > 0){
            List<ScheduleTask> scheduleTasks = new ArrayList<>();
            scheduleTasks.addAll(allTask.values());
            return scheduleTasks;
        }

        return null;
    }

    @Override
    public ScheduleTask getTaskById(int id) {
        return null;
    }

    @Override
    public ScheduleTask addScheduleTask(ScheduleTask scheduleTask)throws Exception{
        // 获取调度器
        Scheduler scheduler = schedulerFactoryBean.getScheduler();

        // 构建当前调度器的具体作业对象
        JobDetail jobDetail = JobBuilder.newJob(ScheduleJobProxy.class).
                withIdentity(String.valueOf(scheduleTask.getId()),scheduleTask.getGroupName()).build();

        // 定义当前具体作业对象的参数
        JobDataMap jobDataMap = jobDetail.getJobDataMap();

        Class<?> clazz = Class.forName(scheduleTask.getGroupName());
        // 与sping集成
        Object target = null;
        if(null == this.applicationContext.getBean(clazz)){
            target = clazz.newInstance();
        }else{
            target = this.applicationContext.getBean(clazz);
        }
        jobDataMap.put(ScheduleJobProxy.DATA_TARGET_KEY,target);

        Method method = clazz.getMethod(scheduleTask.getTriggerName().replaceAll(scheduleTask.getGroupName()+".",""));
        jobDataMap.put(ScheduleJobProxy.DATA_TRIGGER_KEY,method);

        jobDataMap.put(ScheduleJobProxy.DATA_TASK_KEY,scheduleTask);
        jobDataMap.put(ScheduleJobProxy.DATA_TRIGGER_PARAM_KEY,new Object[]{});


        // 构建作业调度器
        CronTrigger cronTrigger = TriggerBuilder.newTrigger().
                withIdentity(String.valueOf(scheduleTask.getId()),scheduleTask.getGroupName()).
                withSchedule(CronScheduleBuilder.cronSchedule(scheduleTask.getCron())).build();

        scheduler.scheduleJob(jobDetail,cronTrigger);

        if(!scheduler.isShutdown()){

            scheduler.start();
        }

        // 保存当前任务
        if(!allTask.containsKey(scheduleTask.getId())){
            allTask.put(String.valueOf(scheduleTask.getId()),scheduleTask);
        }

        return scheduleTask;
    }

    private ScheduleTask createScheduleTask(Method method){
        ScheduleTask scheduleTask = new ScheduleTask();
        scheduleTask.setId(num++);

        Class clazz = method.getDeclaringClass();
        scheduleTask.setGroupName(clazz.getName());

        scheduleTask.setTriggerName(clazz.getName()+"."+method.getName());

        if(method.isAnnotationPresent(Scheduled.class)){
            // spring管理的定时任务
            Annotation annotation = method.getAnnotation(Scheduled.class);
            Method method1 = null;
            try {
                method1 = annotation.getClass().getMethod("cron");
                String cron = method1.invoke(annotation).toString();
                scheduleTask.setCron(cron);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return scheduleTask;
    }

    @Override
    public ScheduleTask addScheduleTask(String taskName,String taskClassName,String triggerName,String cron) throws Exception {

        Class<?> clazz = Class.forName(taskClassName);
        Method method = clazz.getMethod(triggerName);

        ScheduleTask task = createScheduleTask(method);
        task.setTaskName(taskName);
        task.setCron(cron);

        return addScheduleTask(task);
    }

    @Override
    public int modifyScheduleTask(ScheduleTask scheduleTask) {
        return 0;
    }

    @Override
    public int removeScheduleTask(ScheduleTask scheduleTask) throws SchedulerException {

        // 获取调度器
        Scheduler scheduler = schedulerFactoryBean.getScheduler();
        TriggerKey triggerKey = new TriggerKey(scheduleTask.getTriggerName());
        // 暂停trigger
        scheduler.pauseTrigger(triggerKey);
        // 卸载工作线程
        scheduler.unscheduleJob(triggerKey);
        // 删除Job
        JobKey jobKey = new JobKey(String.valueOf(scheduleTask.getId()));
        scheduler.deleteJob(jobKey);
        return 0;
    }

    @Override
    public void restartScheduleTask(ScheduleTask scheduleTask) {

    }

    @Override
    public int pauseScheduleTask(ScheduleTask scheduleTask) {
        return 0;
    }

    @Override
    public int disabledScheduleTask(ScheduleTask scheduleTask) {
        return 0;
    }

    @Override
    public int shutdownScheduleTask(ScheduleTask scheduleTask) {
        return 0;
    }

    @Override
    public void startAllTask() {

    }

    @Override
    public void shutdownAllTask() {

    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        String[] names = applicationContext.getBeanDefinitionNames();
        for(String name : names){
            Class<?> clazz = applicationContext.getBean(name).getClass();

            Method[] methods = clazz.getMethods();
            for (Method method : methods){
                if(method.isAnnotationPresent(Scheduled.class)){
                    ScheduleTask scheduleTask = createScheduleTask(method);
                    try {
                        addScheduleTask(scheduleTask);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }

        }
    }
}
